package gdou.gym.service.order.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import gdou.gym.dao.*;
import gdou.gym.entity.*;
import gdou.gym.exception.StateCode;
import gdou.gym.exception.SysException;
import gdou.gym.service.order.OrderService;
import gdou.gym.sys.log.Log;
import gdou.gym.sys.order.Remain;
import gdou.gym.util.CreateOrderNo;
import gdou.gym.util.DataUtil;
import gdou.gym.vo.AdminQueryOrderSpaceCostVo;
import gdou.gym.vo.AdminQueryOrderVo;
import gdou.gym.vo.MyPageInfo;
import gdou.gym.vo.OrderViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.*;

@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrdersMapper ordersMapper;
    @Resource
    private SpaceTimeMapper spaceTimeMapper;
    @Resource
    private SpaceMapper spaceMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private OrderViewMapper orderViewMapper;
    @Resource
    private OrderSpaceViewMapper orderSpaceViewMapper;
    @Resource
    private OrderDateViewMapper orderDateViewMapper;

    @Resource
    private Remain remain;


    @Override
    public Map<String, Object> queryAllOrderByCondition(MyPageInfo<AdminQueryOrderVo> info) {
        OrderViewExample orderViewExample = new OrderViewExample();
        OrderViewExample.Criteria criteria = orderViewExample.createCriteria();
        AdminQueryOrderVo vo = info.getQueryInfo();

        if (vo.getType() != null) {
            criteria.andOrderSpaceNameEqualTo(vo.getType());
        }
        if (vo.getState() != null) {
            criteria.andStateEqualTo(vo.getState() == 1);
        }
        if (vo.getStartData() != null) {
            criteria.andOrderDataGreaterThanOrEqualTo(vo.getStartData());
        }
        if (vo.getEndData() != null) {
            criteria.andOrderDataLessThanOrEqualTo(vo.getEndData());
        }
        orderViewExample.setOrderByClause("substring(order_no,3) DESC");
        PageHelper.startPage(info.getPageNo(), info.getPageSize());
        List<OrderView> orderViews = orderViewMapper.selectByExample(orderViewExample);
        PageInfo<OrderView> pageInfo = new PageInfo<>(orderViews);
        List<OrderViewVo> result = new LinkedList<>();
        for (OrderView ov : pageInfo.getList()) {
            result.add(new OrderViewVo(ov));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("list", result);
        map.put("total", pageInfo.getTotal());
        return map;
    }


    @Transactional
    @Log
    /*用户订单*/
    public void addOrder(Integer spaceTimeId, String account) {
        try {
            SpaceTime spaceTime = spaceTimeMapper.selectByPrimaryKey(spaceTimeId);
            Space space = spaceMapper.selectByPrimaryKey(spaceTime.getNo());
            User user = userMapper.selectByPrimaryKey(account);
            Orders order = new Orders(spaceTime, space);
            /*只用订单表新增，拦截器处理了*/
            order.setAccount(account);
            order.setNo(CreateOrderNo.createOrder(user.getType()));
            ordersMapper.insert(order);
        } catch (RuntimeException e) {
            remain.increase(spaceTimeId, 1);
            throw new SysException(StateCode.ORDER_CREATE_ERR);
        }
    }

    @Override
    /*用户插叙自己的订单信息*/
    public List<OrderViewVo> queryMyOrderMsg(String account) {
        OrderViewExample orderViewExample = new OrderViewExample();
        orderViewExample.createCriteria().andOrderAccountEqualTo(account);
        List<OrderView> myOrder = orderViewMapper.selectByExample(orderViewExample);
        List<OrderViewVo> myOrderVo = new LinkedList<>();
        for (OrderView o : myOrder) {
            myOrderVo.add(new OrderViewVo(o));
        }
        return myOrderVo;
    }

    @Override
    @Transactional
    @Log
    /*用户取消订单*/
    public void cancelOrder(String orderNo) {
        try {
            OrderViewExample orderViewExample = new OrderViewExample();
            orderViewExample.createCriteria().andOrderNoEqualTo(orderNo);
            /*先查询该订单号对应预约的时间日期场次*/
            List<OrderView> orderViews = orderViewMapper.selectByExample(orderViewExample);
            if (orderViews.size() != 1) {
                throw new RuntimeException();
            }
            OrderView ov = orderViews.get(0);
            /*更新订单*/
            ordersMapper.updateStateByPrimaryKey(orderNo);
            /*更新余量表*/
            //   spaceTimeMapper.cancelOrder(ov.getOrderSpaceNo(), ov.getOrderData(), ov.getOrderTime());

            /*更新内存的表*/
            int id = spaceTimeMapper.getIdByDataAndTimeAndNo(ov.getOrderData(), ov.getOrderTime(), ov.getOrderSpaceNo());
            //     remain.getRemainMap().compute(id, (k, v) -> v == null ? 1 : ++v);
            remain.increase(id, 1);
        } catch (RuntimeException e) {
            throw new SysException(StateCode.Cancel_ERROR);
        }
    }

    @Override
    /*查询场地订单的预约数量*/
    public Collection<Object> queryOrderSpaceMsg() {
        Map<String, Object> stringIntegerMap = orderSpaceViewMapper.queryOrderSpaceMsg();
        return stringIntegerMap.values();
    }

    @Override
    /*查询场地订单的预约金额*/
    public List<AdminQueryOrderSpaceCostVo> queryOrderSpaceCostMsg() {
        return orderViewMapper.queryOrderSpaceCostMsg();
    }

    /*查询近7天预约记录*/
    @Override
    public Map<String, Double> searchRecentOrder(String curDate, Integer beforeThisDaysNums) {
        OrderDateViewExample ov = new OrderDateViewExample();
        String before = DataUtil.getThisDayBeforeByNums(curDate, beforeThisDaysNums);
        ov.createCriteria().andOrderDataBetween(before, curDate);
        List<OrderDateView> orderDateViews = orderDateViewMapper.selectByExample(ov);
        List<String> dateList = DataUtil.getThisDayAfterByNumsList(curDate, beforeThisDaysNums);
        Map<String, Double> map = new LinkedHashMap<>(beforeThisDaysNums);
        for (String date : dateList) {
            map.put(date, 0.0);
        }
        for (OrderDateView o : orderDateViews) {
            map.merge(o.getOrderData(), o.getOrderCost(), Double::sum);
        }
        return map;
    }


}
